package com.kstech.mp3604.manager.serialComm

import android.content.Context
import com.blankii.androidlibrary.exts.logd
import com.blankii.androidlibrary.exts.logi
import com.blankj.utilcode.util.SPUtils
import com.kstech.mp3604.base.Global
import com.kstech.mp3604.base.Global.ANGLE
import com.kstech.mp3604.base.Global.INNER_ARC
import com.kstech.mp3604.base.Global.ONE_LINE_LENGTH
import com.kstech.mp3604.base.Global.OUTER_ARC
import com.kstech.mp3604.base.Global.TWO_LINE_LENGTH
import com.kstech.mp3604.base.Global.WARE_HOUSE_SETTING_ID
import com.kstech.mp3604.base.HomeViewModel
import com.kstech.mp3604.utils.DataUtil
import com.kstech.mp3604.utils.DataUtil.hexToBytesArr
import com.yujing.yserialport.YListener
import com.yujing.yserialport.YSerialPort
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

/**
 * author: blankii
 * created on: 2025/3/17 17:17
 * description:
 *
 *
 * **************串口转CAN****************
 * 辰想平板使用致远电子 UART转CAN模块
 * 使用android-serial-api 发送串口数据，自动转化为CAN
 * CAN波特率配置为250k UART波特率115200 端口tty5
 *
 *
 * ***********实时向控制器发送的数据**********
 * 每200ms 发送0190 以及 心跳
 * 通讯故障：与笔记本pcan-view测试，前期uart发送异常，接收正常，后调整发送间隔，注意测试观察效果
 * ***************************************
 *
 */
object SerialManager {

    private var ySerialPort: YSerialPort? = null
    private lateinit var mHomeViewModel: HomeViewModel
    var threadLive = true
//    private var serialState = true


    private var rev0210Listener: Rev_0210_Listener? = null
    fun setRev0210Listener(rev0210Listener: Rev_0210_Listener) {
        this.rev0210Listener = rev0210Listener

    }

    private var rev0310Listener: Rev_0310_Listener? = null
    fun setRev0310Listener(rev0310Listener: Rev_0310_Listener) {
        this.rev0310Listener = rev0310Listener
    }

    private var rev0410Listener: Rev_0410_Listener? = null
    fun setRev0410Listener(rev0410Listener: Rev_0410_Listener) {
        this.rev0410Listener = rev0410Listener
    }

    private lateinit var serialCommStatusListener: SerialCommStatusListener
    private var yj_zdhw_zdhz = ""

    fun onDestroy() {
        ySerialPort!!.onDestroy()
        threadLive = false
    }

    fun onResume() {
//        serialState = true
//        ySerialPort!!.reStart()
    }

    fun onPause() {
//        serialState = false
    }

    fun clearAllListener() {
        rev0210Listener = null
        rev0310Listener = null
        rev0410Listener = null
    }

    /**
     * 发送心跳
     * 一直向0710 发送05
     */
    fun startHeartBeat() {
        CoroutineScope(Dispatchers.IO).launch {
            while (threadLive) {
                /**
                 * 如果屏幕状态在线并且can线连接上才会发送
                 */
//                serialState &&
                if (mHomeViewModel.serialCommIsConnect.value == true) {
                    "自动横移尺寸(mm):${Global.app_autoHY_value},重量:${mHomeViewModel.device_weight.value}kg,实时_横移:${Global.mSpeedHY},实时_起升:${Global.mSpeedQS},实时_接触:${Global.mSpeedJC},x:${mHomeViewModel.device_posX.value},y:${mHomeViewModel.device_posY.value},z:${mHomeViewModel.device_posZ.value},规则_起升:${Global.currentSpeedQS},规则_横移:${Global.currentSpeedHY},规则_接触:${Global.currentSpeedJC},state:${mHomeViewModel.device_state.value!!.name}".logi(
                        "控制器数据"
                    )
                    sendSerial(packUpHeartBeat())
                    delay(100)
                    send0190(
                        Global.currentSpeedQS,
                        Global.currentSpeedHY,
                        Global.currentSpeedJC,
                        Global.app_autoHY_value,
                    )
                }
                "串口在线状态:${mHomeViewModel.serialCommIsConnect.value},服务器在线状态:${mHomeViewModel.socketCommIsConnect.value}".logi(
                    "设备在线状态"
                )
                checkIsSerialOnLine()
                delay(100)
            }
        }
    }

    fun checkIsSerialOnLine() {
        if (count >= 10) {
            //断线
            if (isConnect) {
                serialCommStatusListener.isUnConnect()
                isConnect = false
            }
        } else {
            //在线
            if (!isConnect) {
                serialCommStatusListener.isConnect()
                isConnect = true
            }
        }

//        count.toString().logi("串口---生命周期")
        count++
    }

    /**
     * 监控串口通讯是否正常
     * 隔段时间监控能否收到消息
     */
    private var isConnect = false //避免重复刷新ui
    private var count: Long = 10 //如果超时一秒判断串口通讯断开

    // 串口使用115200， 与控制器连接的can 配置250k
    fun openSerial(
        homeViewModel: HomeViewModel, context: Context, listener: SerialCommStatusListener
    ) {
        this.mHomeViewModel = homeViewModel
        this.serialCommStatusListener = listener
        ySerialPort = YSerialPort(context, "/dev/ttyS5", "115200").apply {
            addDataListener { hexString, bytes ->
                //监控在线状态标识
                count = 0
                //处理接收数据
                upPackHexString(hexString)
            }
            start()
        }
//        ySerialPort.setToAuto()
        startHeartBeat()
    }


    /**
     * 没有自定义协议转化 02 10 01 02 03 04 05 06 07 08
     * 两个字节id，八个字节数据 共十字节 20字符
     * 有自定义协议转化  40 0B 00 '02 10 01 02 03 04 05 06 07 08' 1A
     * 40 帧头
     * 0B 数据个数
     * 00 帧信息
     * 1A 帧尾
     */
//    fun upPackHexString(hexString: String?) {
//        if (hexString.isNullOrEmpty()) {
//            return
//        }
//        val hexString = hexString.replace(" ", "").replace("\n", "")
//        if (hexString.length % 28 != 0) {
//            return
//        }
//        val hexList = hexString.chunked(28)
//
//        hexList.forEachIndexed { index, itemHexString ->
////            itemHexString.loge(TAG)
//            checkHexStringValid(itemHexString)?.let {
////                "data===>$it".loge(TAG)
//                parseData(it)
//            }
//        }
//    }

    /**
     * 透明带标识转换
     * 长度 2
     */
    fun upPackHexString(hexString: String?) {
        if (hexString.isNullOrEmpty()) {
            return
        }
        val hexString = hexString.replace(" ", "").replace("\n", "")
        if (hexString.length % 20 != 0) {
            return
        }
        val hexList = hexString.chunked(20)

        hexList.forEachIndexed { index, itemHexString ->
            parseData(itemHexString)
        }
    }


    private fun parseData(it: String) {
        when (it.take(4)) {
            "0210" -> {
                //行进速度
                val xjs = DataUtil.hexToSInt(it.substring(4, 8))
                //横移速度
                val hys = DataUtil.hexToSInt(it.substring(8, 12))
                //起升速度
                val qss = DataUtil.hexToSInt(it.substring(12, 16))
                //接近速度
                val jjs = DataUtil.hexToSInt(it.substring(16, 20))
                rev0210Listener?.data_0210(xjs, hys, qss, jjs)
            }

            "0310" -> {
//                "xyz:${it.substring(4, 20)}".loge("Blankii")
                //x
                val x = DataUtil.hexToSLong(it.substring(4, 12))
                //y
                val y = DataUtil.hexToSInt(it.substring(12, 16))
                //z
                val z = DataUtil.hexToSInt(it.substring(16, 20))

                rev0310Listener?.data_0310(x, y, z)
            }

            "0410" -> {
                // 转换为十进制数值（0-255）
                val byte0 = it.substring(4, 6).toInt(16)
                val byte1 = it.substring(6, 8).toInt(16)
                val byte2 = it.substring(8, 10).toInt(16)
                //吊重kg
                val dz = DataUtil.hexToUInt(it.substring(10, 14))
                //故障码索引
                val byte4 = it.substring(14, 16).toInt(16) //转十进制
                //故障码
                val byte5 = it.substring(16, 20)

                // 提取 8 位二进制数组（低位在前）
                val arr0 = IntArray(8) { index ->
                    (byte0 shr index) and 0x01
                }
                val arr1 = IntArray(8) { index ->
                    (byte1 shr index) and 0x01
                }
                val arr2 = IntArray(8) { index ->
                    (byte2 shr index) and 0x01
                }
                //应急
                val yj = arr0[0]
                //自动回正（行走）
                val zdhz = arr0[1]
                //自动回位(吊具)
                val zdhw = arr0[2]
                //直线0  弧线1
                val isZhiXian = arr0[3]
                //正常0 故障1
                val isError = arr0[4]
                //行走0 堆码1
                val isOpenCamera = arr0[5]
                //前保护
                val qbhState = arr0[6]
                //后保护
                val hbhState = arr0[7]
                //线控在线
                val isXK = arr1[0]
                //左转电机在线
                val isZZDJ = arr1[1]
                //右转电机在线
                val isYZDJ = arr1[2]
                //左驱电机在线
                val isZQDJ = arr1[3]
                //右驱电机在线
                val isYQDJ = arr1[4]
                //吊装在线
                val isDZ = arr1[5]
                //光电开关
                val gdState = arr1[6]
                //吊重状态 实时0 起吊1
                val dzState = arr2[0]

                rev0410Listener?.data1_0410(byte4, byte5)
                val newCombinedValue = "$yj$zdhz$zdhw"
                if (yj_zdhw_zdhz != newCombinedValue) {
                    yj_zdhw_zdhz = newCombinedValue
                    rev0410Listener?.data2_0410(yj, zdhz, zdhw)
                }
                rev0410Listener?.data3_0410(
                    isXK, isZZDJ, isYZDJ, isZQDJ, isYQDJ, isDZ
                )
                rev0410Listener?.data4_0410(isZhiXian, isError, isOpenCamera)
                serialCommStatusListener.serialFaultState(isError)
                rev0410Listener?.data5_0410(dz, dzState)
                rev0410Listener?.data6_0410(qbhState, hbhState, gdState)
            }

            "0610" -> {
                //命令符  判断命令是不是40 是的话 回43读响应四个字节
                val cs = it.substring(4, 6)
                if (cs == "40") {
                    //判断参数索引地址
                    val addressHex = it.substring(6, 10)
                    val indexHex = it.substring(10, 12)
                    when (DataUtil.hexL2B(addressHex)) {
                        //口1长度
                        "2100" -> {
                            sendSerial(
                                packUp590(
                                    "2100", DataUtil.intToHex4(
                                        SPUtils.getInstance().getInt(ONE_LINE_LENGTH)
                                    )
                                )
                            )
                        }
                        //口2长度
                        "2101" -> {
                            sendSerial(
                                packUp590(
                                    "2101", DataUtil.intToHex4(
                                        SPUtils.getInstance().getInt(TWO_LINE_LENGTH)
                                    )
                                )
                            )
                        }
                        //内弧半径
                        "2102" -> {
                            sendSerial(
                                packUp590(
                                    "2102", DataUtil.intToHex4(
                                        SPUtils.getInstance().getInt(INNER_ARC)
                                    )
                                )
                            )
                        }
                        //外弧半径
                        "2103" -> {
                            sendSerial(
                                packUp590(
                                    "2103",
                                    DataUtil.intToHex4(SPUtils.getInstance().getInt(OUTER_ARC))
                                )
                            )
                        }
                        //角度
                        "2104" -> {
                            sendSerial(
                                packUp590(
                                    "2104", DataUtil.intToHex4(
                                        (SPUtils.getInstance().getFloat(ANGLE) * 100).toInt()
                                    )
                                )
                            )
                        }
                        //洞口位置
                        "2105" -> {
                            val whsi = SPUtils.getInstance().getInt(WARE_HOUSE_SETTING_ID)
                            sendSerial(packUp590("2105", DataUtil.intToHex4(whsi)))
                        }
                        //弹种：280
                        "2106" -> {
                            when (indexHex) {
                                "01" -> {
                                    sendSerial(
                                        packUp590(
                                            "2106", DataUtil.intToHex4(Global.speedQS[0]), indexHex
                                        )
                                    )
                                }

                                "02" -> {
                                    sendSerial(
                                        packUp590(
                                            "2106", DataUtil.intToHex4(Global.speedHY[0]), indexHex
                                        )
                                    )
                                }

                                "03" -> {
                                    sendSerial(
                                        packUp590(
                                            "2106", DataUtil.intToHex4(Global.speedJC[0]), indexHex
                                        )
                                    )
                                }

                                "04" -> {
                                    sendSerial(
                                        packUp590(
                                            "2106", DataUtil.intToHex4(Global.speedHZ[0]), indexHex
                                        )
                                    )
                                }
                            }
                        }
                        //弹种：500
                        "2107" -> {
                            when (indexHex) {
                                "01" -> {
                                    sendSerial(
                                        packUp590(
                                            "2107", DataUtil.intToHex4(Global.speedQS[1]), indexHex
                                        )
                                    )
                                }

                                "02" -> {
                                    sendSerial(
                                        packUp590(
                                            "2107", DataUtil.intToHex4(Global.speedHY[1]), indexHex
                                        )
                                    )
                                }

                                "03" -> {
                                    sendSerial(
                                        packUp590(
                                            "2107", DataUtil.intToHex4(Global.speedJC[1]), indexHex
                                        )
                                    )
                                }

                                "04" -> {
                                    sendSerial(
                                        packUp590(
                                            "2107", DataUtil.intToHex4(Global.speedHZ[1]), indexHex
                                        )
                                    )
                                }
                            }
                        }
                        //弹种：16A
                        "2108" -> {
                            when (indexHex) {
                                "01" -> {
                                    sendSerial(
                                        packUp590(
                                            "2108", DataUtil.intToHex4(Global.speedQS[2]), indexHex
                                        )
                                    )
                                }

                                "02" -> {
                                    sendSerial(
                                        packUp590(
                                            "2108", DataUtil.intToHex4(Global.speedHY[2]), indexHex
                                        )
                                    )
                                }

                                "03" -> {
                                    sendSerial(
                                        packUp590(
                                            "2108", DataUtil.intToHex4(Global.speedJC[2]), indexHex
                                        )
                                    )
                                }

                                "04" -> {
                                    sendSerial(
                                        packUp590(
                                            "2108", DataUtil.intToHex4(Global.speedHZ[2]), indexHex
                                        )
                                    )
                                }
                            }
                        }
                        //弹种：YH
                        "2109" -> {
                            when (indexHex) {
                                "01" -> {
                                    sendSerial(
                                        packUp590(
                                            "2109", DataUtil.intToHex4(Global.speedQS[3]), indexHex
                                        )
                                    )
                                }

                                "02" -> {
                                    sendSerial(
                                        packUp590(
                                            "2109", DataUtil.intToHex4(Global.speedHY[3]), indexHex
                                        )
                                    )
                                }

                                "03" -> {
                                    sendSerial(
                                        packUp590(
                                            "2109", DataUtil.intToHex4(Global.speedJC[3]), indexHex
                                        )
                                    )
                                }

                                "04" -> {
                                    sendSerial(
                                        packUp590(
                                            "2109", DataUtil.intToHex4(Global.speedHZ[3]), indexHex
                                        )
                                    )
                                }
                            }
                        }
                        //弹种：122
                        "210A" -> {
                            when (indexHex) {
                                "01" -> {
                                    sendSerial(
                                        packUp590(
                                            "210A", DataUtil.intToHex4(Global.speedQS[4]), indexHex
                                        )
                                    )
                                }

                                "02" -> {
                                    sendSerial(
                                        packUp590(
                                            "210A", DataUtil.intToHex4(Global.speedHY[4]), indexHex
                                        )
                                    )
                                }

                                "03" -> {
                                    sendSerial(
                                        packUp590(
                                            "210A", DataUtil.intToHex4(Global.speedJC[4]), indexHex
                                        )
                                    )
                                }

                                "04" -> {
                                    sendSerial(
                                        packUp590(
                                            "210A", DataUtil.intToHex4(Global.speedHZ[4]), indexHex
                                        )
                                    )
                                }
                            }
                        }
                    }
                }
            }

            else -> {
            }
        }
    }

    /**
     * 数据符合规范，进一步加工解析反回  判断帧头 帧尾 数据长度
     * 数据不符合规范，直接反回null，让循环自动执行下一个
     */
//    private fun checkHexStringValid(hexString: String): String? {
    //检查自定义帧头 帧尾
//        if (hexString.substring(0, 2) == FRAME_HEADER && hexString.substring(26, 28) == FRAME_END) {
//            return hexString.substring(6, 26)
//        } else {
//            return null
//        }
    //透明传输 2

//    }

    /**
     * hexStr:十六进制的没有空格的字符串
     * 比如01ffaa3132
     * 给数据添加帧头 数据长度 帧信息 帧尾
     */
    fun sendSerial(hexStr: String) {
        hexStr.logd("控制器-源数据")
        ySerialPort!!.send(hexToBytesArr(hexStr), object : YListener<Boolean> {
            override fun value(value: Boolean?) {
//                    "$value".loge("发送serial")
            }
        }, object : YListener<Int> {
            override fun value(value: Int?) {
//                    "$value".loge("发送serial-int")
            }
        })

    }


    /**
     * canId:双字节 01 00
     * hexData: 八个字节  ff ff ff ff ff ff ff ff
     */
    fun packUpSendData(canId: String, hexData: String): String {
        return canId + hexData
    }

    /*
    执行：packSDOW("2007", DataUtil.intToLittleEndianHex4(1000000000)) 返回：05904b07200000ca9a3b
    0590:canId
    34:cs 标识符 统一写四个字节
    00:子序列 基本都是00
    00ca9a3b:1000000000 十六进制小端序
     */
    fun packUp590(addressHex: String, dataHex: String, indexHex: String = "00"): String {
//        return "0590${getByteCount(dataHex)}b${hexToL(addHex)}00$dataHex"
        return "059043${DataUtil.hexB2L(addressHex)}${indexHex}$dataHex"
    }

    /**
     * sjsd 升降限速
     * hysd 横移限速
     * jcsd 接触限速
     * autoHy 自动横移位置（mm）
     */
    fun send0190(sjsd: Int, hysd: Int, jcsd: Int, autoHy: Int) {
        sendSerial(
            packUpSendData(
                "0190",
                "${DataUtil.sIntToHex(sjsd)}${DataUtil.sIntToHex(hysd)}${DataUtil.sIntToHex(jcsd)}${
                    DataUtil.sIntToHex(
                        autoHy
                    )
                }"
            )
        )
    }

    fun packUp290(x: Int, y: Int, z: Int): String {
        return packUpSendData(
            "0290", "${DataUtil.intToHex4(x)}${DataUtil.intToHex2(y)}${DataUtil.intToHex2(z)}"
        )
    }

    private fun packUpHeartBeat(): String {
        return packUpSendData("0710", "0500000000000000")
    }


    interface Rev_0210_Listener {
        fun data_0210(data1: Int, data2: Int, data3: Int, data4: Int)
    }

    interface Rev_0310_Listener {
        fun data_0310(data1: Long, data2: Int, data3: Int)
    }

    interface Rev_0410_Listener {
        fun data1_0410(data1: Int, data2: String)
        fun data2_0410(data1: Int, data2: Int, data3: Int)
        fun data3_0410(
            data1: Int, data2: Int, data3: Int, data4: Int, data5: Int, data6: Int
        )

        fun data4_0410(
            data1: Int, data2: Int, data3: Int
        )

        fun data5_0410(data1: Int, data2: Int)

        fun data6_0410(data1: Int, data2: Int, data3: Int)
    }

    interface UiListener {
        fun data0610IsNotExists()
    }

    /**
     * 发送标标定2000-2008 自复位 先发送0 再发送1
     * 2009 发送值就行不需要自复位
     */
    fun sendBiaoDingById(address: String, listener: SerialUiListener) {
        CoroutineScope(Dispatchers.IO).launch {
            // 先发一个0
            sendSerial(packUp590(address, DataUtil.intToHex4(0)))
            delay(100)
            // 先发一个1
            sendSerial(packUp590(address, DataUtil.intToHex4(1)))
            delay(100)
            sendSerial(packUp590(address, DataUtil.intToHex4(1)))
            delay(100)
            // 先发一个0
            sendSerial(packUp590(address, DataUtil.intToHex4(0)))
            withContext(Dispatchers.Main) {
                listener.finishedBiaoDing()
            }
        }
    }

    /**
     * 发送出厂测试模式 address=2009
     */
    fun sendFactoryModel(factoryValue: Int, listener: SerialUiListener) {
        sendSerial(packUp590("2009", DataUtil.intToHex4(factoryValue)))
        listener.finishedBiaoDing()
    }
}